********************************************************************** * Mega Man X Password System * * by Manxome Bromide, 6/2023 * * ManxomeBromide@gmail.com * ********************************************************************** I. Introduction II. Creating A Password A. The Password Checklist B. Obfuscation C. Assembling the Digits III. A Worked Example IV. Some Sample Passwords V. Technical Notes I. INTRODUCTION This document outlines the password system in Mega Man X for the Super Nintendo Entertainment System. It presents it in a worksheet-like format that will let you begin with a list of items and end with a working password. This format skips over the technical details of how the digits of the password are actually assembled or decoded by the game logic itself; advanced readers or ROM hackers may consult Chapter V, which explains the places where game code's algorithm differs from the procedure in this document, as well as the locations of the code and data tables it uses. Unmodified copies of this document may be copied, distributed, or hosted on any site for any purpose. II. Creating a Password This section provides a set of instructions that you can use to generate a password for any game state. II-A. The Password Checklist The data that is stored in the password can be represented as 36 checkboxes. Select the values you want from this list. Entries marked as "ANY VALUE" can be checked or not at your whim; this will change the digits in the password but it won't change the state of the game once you put the password in. For entries marked PARITY, count the number of checked boxes from the rows listed, and check the PARITY box if there are an ODD number of boxes. Leave it unchecked if there are an EVEN number of checked boxes. Also note that if you check any boxes at all representing upgrades, you must also check the "Completed Intro Highway stage" entry. 1. [ ] Helmet Upgrade 2. [ ] Arm/Weapon Upgrade 3. [ ] Body/Armor Upgrade 4. [ ] Leg Upgrade 5. [ ] Sub Tank from Storm Eagle stage 6. [ ] Sub Tank from Armored Armadillo stage 7. [ ] Sub Tank from Spark Mandrill stage 8. [ ] Sub Tank from Flame Mammoth stage 9. [ ] Heart Container from Chill Penguin stage 10. [ ] Heart Container from Armored Armadillo stage 11. [ ] Heart Container from Storm Eagle stage 12. [ ] Heart Container from Sting Chameleon stage 13. [ ] Heart Container from Flame Mammoth stage 14. [ ] Heart Container from Boomer Kuwanger stage 15. [ ] Heart Container from Spark Mandrill stage 16. [ ] Heart Container from Launch Octopus stage 17. [ ] Homing Torpedo weapon 18. [ ] Chameleon Sting weapon 19. [ ] Rolling Shield weapon 20. [ ] Fire Wave weapon 21. [ ] Storm Tornado weapon 22. [ ] Electric Spark weapon 23. [ ] Boomerang Cutter weapon 24. [ ] Shotgun Ice weapon 25. [ ] ANY VALUE 26. [ ] PARITY: 17,18,19,20,21,22,23,24 27. [ ] PARITY: 9,10,11,12,13,14,15,16 28. [ ] PARITY: 1,2,3,4,5,6,7,8 29. [ ] Completed Intro Highway stage 30. [ ] ANY VALUE 31. [ ] ANY VALUE 32. [ ] ANY VALUE 33. [ ] PARITY: 1,5,9,13,17,21,25,29 34. [ ] PARITY: 2,6,10,14,18,22,26,30 35. [ ] PARITY: 3,7,11,15,19,23,27,31 36. [ ] PARITY: 4,8,12,16,20,24,28,32 A fun, if somewhat enraging bit of trivia: entry 25, in the game, is checked exactly when we have earned the Easter-egg Hadouken weapon. The password decoder routine even captures that information during decoding and assigns you the Hadouken weapon during decoding... but then it takes it away from you just before continuing the game! Entries 30, 31, and 32, meanwhile, seem to be assigned at random as a way to make the password more difficult to crack. II-B. Obfuscation Now that we have our initial selections and parity bits, we now scramble the results a little before proceeding. This is a four step process: 1. If entry 29 is checked, flip the checkboxes at entries 1, 5, 9, 13, 17, and 21. To flip a checkbox, check it if it was unchecked, and uncheck it if it was checked. Do not adjust any of the entries marked PARITY to reflect this change. 2. If entry 30 is checked, flip the checkboxes at entries 2, 6, 10, 14, 18, and 22. 3. If entry 31 is checked, flip the checkboxes at entries 3, 7, 11, 15, 19, and 23. 4. If entry 32 is checked, flip the checkboxes at entries 4, 8, 12, 16, 20, and 24. Entries 30 through 32, you may recall, are randomly selected. The effect of this step is to make it so that we have eight equivalent but wildly different-looking passwords for each possible game state. II-C. Assembling the Digits Each of the 12 digits of the password is built out of three of our checkboxes. The process of transforming them is a bit involved; first, for each digit, we consult the three checkboxes and turn them into a number between 0 and 7. Then, we take that preliminary number and turn it into the actual password digit with a substitution table. In this document we'll start by converting all the checkboxes at once into a preliminary password, and then substitute the digits all at once to turn the preliminary password into the final one. Converting checkboxes into the digits of the preliminary password is a matter of simple addition: the first checkbox adds 4 to the value if it's checked, the second adds 2, and the third adds 1. Use the table below to create your sums. Digit | +4 | +2 | +1 | ---------+----+----+----+---- 1. | 6 | 9 | 36 | 2. | 1 | 20 | 27 | 3. | 8 | 13 | 30 | 4. | 11 | 21 | 32 | 5. | 3 | 17 | 34 | 6. | 14 | 23 | 28 | 7. | 2 | 19 | 33 | 8. | 12 | 22 | 29 | 9. | 4 | 10 | 35 | 10. | 5 | 18 | 31 | 11. | 7 | 16 | 26 | 12. | 15 | 24 | 25 | As an example, to generate the first digit of our code, we start with zero and add 4 if entry 6 is checked, 2 if entry 9 is checked, and 1 if entry 36 is checked. If all are checked, that will add up to 7, and if none are, that will add up to zero. Proceeding through the table, we can create the entire 12-digit preliminary password. It would be pretty great if we could turn the preliminary password into the final one by just, say, adding 1 to each number, or turning all the 0s into 8s. Alas, it is not so simple. Instead, each digit has its own substitution code. To get the final password, work through each digit in your code one at a time, consulting each row in the table below in turn. Select the column for the value of the digit in that place, and copy that digit into place in the final passcode. Digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ---------+---+---+---+---+---+---+---+---+--- 1. | 7 | 2 | 1 | 4 | 8 | 3 | 6 | 5 | 2. | 6 | 5 | 4 | 1 | 7 | 8 | 3 | 2 | 3. | 7 | 5 | 6 | 1 | 4 | 3 | 2 | 8 | 4. | 1 | 3 | 8 | 5 | 7 | 6 | 4 | 2 | 5. | 2 | 3 | 5 | 7 | 4 | 6 | 1 | 8 | 6. | 8 | 2 | 4 | 7 | 1 | 3 | 6 | 5 | 7. | 4 | 5 | 1 | 8 | 7 | 3 | 2 | 6 | 8. | 4 | 8 | 5 | 7 | 1 | 2 | 3 | 6 | 9. | 3 | 7 | 5 | 2 | 1 | 8 | 6 | 4 | 10. | 2 | 5 | 1 | 4 | 8 | 7 | 3 | 6 | 11. | 8 | 7 | 2 | 6 | 4 | 1 | 5 | 3 | 12. | 4 | 7 | 1 | 3 | 8 | 2 | 6 | 5 | For example, if the fourth digit in our code so far is a 3, we look at the column for 3 at the row for 4 and find the result is a 5. The fourth digit in the final password will be a 5. III. A Worked Example Let's take a pretty simple example; let's assume we've beaten our first real stage but didn't find any secrets along the way. We'll check entry 24 to mark that we beat Chill Penguin, entry 4 because the Leg upgrade was a mandatory pickup along the way, and entry 29 since we have to beat the intro to get that far. We'll also check boxes 30 and 32 to mix things up a bit, but leave 25 and 31 blank. Now that we have our choices, we need to compute parity; we have to check 26 (1 item set), 28 (1 item set), and 33 (1 item set), but not 27 (no items set), 34 (2 items set), 35 (no items set) or 36 (4 items set). We now have entries 4, 24, 26, 28, 29, 30, 32, and 33 set. Now it's time for the obfuscation step. 29, 30, and 32 are checked, so we need to flip the values at 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, 21, 22, and 24. That's a lot, and it's mostly turning on empty values. The new set is 1, 2, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, 21, 22, 26, 28, 29, 30, 32, and 33. From here we can create our preliminary password: 1. 4 ( 6) + 2 ( 9) = 6 2. 4 ( 1) + 2 (20) = 6 3. 4 ( 8) + 2 (13) + 1 (30) = 7 4. 2 (21) + 1 (32) = 3 5. 2 (17) = 2 6. 4 (14) + 1 (28) = 5 7. 4 ( 2) + 1 (33) = 5 8. 4 (12) + 2 (22) + 1 (29) = 7 9. 2 (10) = 2 10. 4 ( 5) + 2 (18) = 6 11. 2 (16) + 1 (26) = 3 12. = 0 Cross-indexing with the digit translation table give us the final password value: 6385-5336-5364. IV. Some Sample Passwords The very beginning of the game: 7671-2844-3284 Skip the intro: 6718-7137-5384 All powerups, but no weapons: 8648-5662-4524 All weapons, but no powerups: 6317-6138-2746 All collectibles, hadouken not marked: 3676-4667-5148 All collectibles, hadouken marked: 2653-3848-7587 V. Technical Notes The actual algorithm used by the game program is not quite the same as what I describe above: * The 36 entries are mapped into five bytes at $1E60 in LoRAM. They are stored in roughly the order I presented, in increasing byte order and with the least significant bit listed first. (So, entry 8 is the $80 bit in $1E61, while entry 9 is the $01 bit in $1E62.) * The first sixteen entries -- the item collection bitmaps -- are copied directly out of $1F99 and $1F9C, where they are used in-game. All other values are assembled or computed from the game state at password generation time. * Instead of the Parity list I provided for entries 32-36, the final byte in the password data is computed by XORing the first four bytes together, and then XORing the top four bits into the bottom four. * Similarly, the obfuscation step involves copying the top 4 bits of $1e63 to the bottom, and then XORing the first three bytes with the resulting value. * The assembly of the password digits uses a very different technique from what I describe. Instead of indexing three values in a row, it consults a 12x5 table of bitmasks for each bit, bit-shifting the relevant values into place as it goes. * Password digits are stored as 0-7 values at all times; the fact that they appear on the screen as the numbers 1-8 is an artifact of the graphics display. When mapped into the SNES, the encoding routine begins at 80F0A6, with the decoding routine following at 80F1A2. It is very clear from the data tables that encoding was being treated as "primary"; much of the logic in the decoder involves doing linear searches over the same tables to reverse what was a simple lookup in the encoding case. * The encoding routine is at $80F0A6. It creates 5-byte password data at $1E60 in LoRAM. * The decoding routine is at $80F1A2. It turns the user-entered password into a 5-byte data block at $1E6C in LoRAM and then processes that result. * The 12x5 digit assembly table is at $86BD24. * The 12x7 digit transposition table is at $86BD6F.